package com.trinity.campus.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.trinity.campus.domain.BindBody;
import com.trinity.campus.domain.CampusStudents;
import com.trinity.campus.domain.CampusUserStudent;
import com.trinity.campus.mapper.CampusStudentsMapper;
import com.trinity.campus.mapper.CampusUserStudentMapper;
import com.trinity.campus.service.ICampusStudentsService;
import com.trinity.common.constant.UserConstants;
import com.trinity.common.core.domain.AjaxResult;
import com.trinity.common.core.domain.TreeSelect;
import com.trinity.common.core.domain.entity.SysDept;
import com.trinity.common.core.domain.entity.SysUser;
import com.trinity.common.exception.ServiceException;
import com.trinity.common.utils.DateUtils;
import com.trinity.common.utils.SecurityUtils;
import com.trinity.common.utils.StringUtils;
import com.trinity.common.utils.bean.BeanValidators;
import com.trinity.system.service.ISysDeptService;
import com.trinity.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.Validator;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 学生Service业务层处理
 *
 * @author trinity
 * @date 2023-11-18
 */
@Service
public class CampusStudentsServiceImpl extends ServiceImpl<CampusStudentsMapper, CampusStudents> implements ICampusStudentsService {

    private static final Logger log = LoggerFactory.getLogger(CampusStudentsServiceImpl.class);
    @Resource
    private CampusStudentsMapper campusStudentsMapper;
    @Resource
    private ISysDeptService sysDeptService;
    @Resource
    protected Validator validator;
    @Resource
    private ISysUserService userService;
    @Resource
    private CampusUserStudentMapper userStudentMapper;

    /**
     * 查询学生
     *
     * @param studentId 学生主键
     * @return 学生
     */
    @Override
    public CampusStudents selectCampusStudentsByStudentId(Long studentId) {
        CampusStudents campusStudents = campusStudentsMapper.selectCampusStudentsByStudentId(studentId);
        this.setSchoolName(campusStudents);
        return campusStudents;
    }

    /**
     * 根据学生直系部门获取祖父级名称
     *
     * @param campusStudents 学生信息
     */
    private void setSchoolName(CampusStudents campusStudents) {
        String ancestors = campusStudents.getSchool().getAncestors();
        Long[] array = Arrays.stream(ancestors.split(","))
                .map(Long::parseLong)
                .toArray(Long[]::new);
        List<SysDept> depts = sysDeptService.selectDeptAncestors(array);
        //排除目录
        List<SysDept> filteredDepts = depts.stream()
                .filter(sysDept -> !"M".equals(sysDept.getDeptType()))
                .collect(Collectors.toList());

        // 将过滤后的 List 转为 Map，以 deptId 作为键
        Map<Long, SysDept> result = filteredDepts.stream()
                .collect(Collectors.toMap(SysDept::getDeptId, sysDept -> sysDept));

        //拼接名称
        String name = "";
        for (Long id : array) {
            SysDept dept = result.get(id);
            if (dept != null)
                if (StringUtils.isBlank(name))
                    name = dept.getDeptName();
                else
                    name = name + "-" + dept.getDeptName();
        }

        campusStudents.getSchool().setDeptName(name + "-" + campusStudents.getSchool().getDeptName());
    }

    /**
     * 查询学生列表
     *
     * @param queryStudentParamsDto 学生
     * @return 学生
     */
    @Override
    public List<CampusStudents> selectCampusStudentsList(CampusStudents queryStudentParamsDto) {
        return campusStudentsMapper.selectCampusStudentsList(queryStudentParamsDto);
    }

    @Override
    public List<CampusStudents> selectCampusStudentsListByDeptId(Long deptId) {
        CampusStudents queryStudentParamsDto = new CampusStudents();
        queryStudentParamsDto.setDeptId(String.valueOf(deptId));
        queryStudentParamsDto.setDelFlag("0");
        return campusStudentsMapper.selectCampusStudentsList(queryStudentParamsDto);
    }

    /**
     * 新增学生
     *
     * @param campusStudents 学生
     * @return 结果
     */
    @Override
    public int insertCampusStudents(CampusStudents campusStudents) {
        campusStudents.setCreateTime(DateUtils.getNowDate());
        return campusStudentsMapper.insertCampusStudents(campusStudents);
    }

    /**
     * 修改学生
     *
     * @param campusStudents 学生
     * @return 结果
     */
    @Override
    public int updateCampusStudents(CampusStudents campusStudents) {
        campusStudents.setUpdateTime(DateUtils.getNowDate());
        return campusStudentsMapper.updateCampusStudents(campusStudents);
    }

    /**
     * 批量删除学生
     *
     * @param studentIds 需要删除的学生主键
     * @return 结果
     */
    @Override
    public int deleteCampusStudentsByStudentIds(Long[] studentIds) {
        return campusStudentsMapper.deleteCampusStudentsByStudentIds(studentIds);
    }

    @Override
    public int setStudentTombstoneByStudentIds(Long[] studentIds) {
        int i = 0;
        for (; i < studentIds.length; i++) {
            UpdateWrapper<CampusStudents> updateWrapper = new UpdateWrapper<>();
            updateWrapper.set("del_flag", "2").eq("student_id", studentIds[i]);
            campusStudentsMapper.update(null, updateWrapper);
        }
        return i;
    }

    /**
     * 删除学生信息
     *
     * @param studentId 学生主键
     * @return 结果
     */
    @Override
    public int deleteCampusStudentsByStudentId(Long studentId) {
        return campusStudentsMapper.deleteCampusStudentsByStudentId(studentId);
    }

    /**
     * 统计数量
     *
     * @param campusStudents 学生
     * @return 结果
     */
    public Long countStudents(CampusStudents campusStudents) {
        return campusStudentsMapper.countStudents(campusStudents);
    }

    /**
     * 导入用户数据
     *
     * @param userList        用户数据列表
     * @param isUpdateSupport 是否更新支持，如果已存在，则进行更新数据
     * @param operator        操作用户
     * @return 结果
     */
    @Override
    public String importUser(List<CampusStudents> userList, Boolean isUpdateSupport, String operator) {
        List<TreeSelect> treeList = findClazz();

        if (StringUtils.isNull(userList) || userList.size() == 0) {
            throw new ServiceException("导入用户数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        Date nowDate = DateUtils.getNowDate();
        for (CampusStudents stu : userList) {
            try {
                //设置班级
                setDeptId(treeList, stu);
                // 验证是否存在这个学生 根据学号
                CampusStudents u = this.selectStudentByStuNo(stu.getStuNo());
                // 不存在直接插入
                if (StringUtils.isNull(u)) {
                    BeanValidators.validateWithException(validator, stu);
                    stu.setCreateBy(operator);
                    stu.setCreateTime(nowDate);
                    stu.setStatus("0");
                    stu.setDelFlag("0");
                    campusStudentsMapper.insert(stu);
                    successNum++;
                    successMsg.append("<br/>").append(successNum).append("、学生 ").append(stu.getStudentName()).append(" 导入成功");
                } else if (isUpdateSupport) {//存在且支持更新
                    BeanValidators.validateWithException(validator, stu);
                    stu.setStudentId(u.getStudentId());
                    stu.setUpdateBy(operator);
                    stu.setUpdateTime(nowDate);
                    stu.setStatus("0");
                    stu.setDelFlag("0");
                    campusStudentsMapper.updateById(stu);
                    successNum++;
                    successMsg.append("<br/>").append(successNum).append("、学生 ").append(stu.getStudentName()).append(" 更新成功");
                } else {//存在不支持更新
                    failureNum++;
                    failureMsg.append("<br/>").append(failureNum).append("、学生 ").append(stu.getStudentName()).append(" 已存在");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、学生 " + stu.getStudentName() + " 导入失败：";
                failureMsg.append(msg).append(e.getMessage());
                log.error(msg, e);
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            log.info(String.valueOf(failureMsg));
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
            log.info(String.valueOf(failureMsg));
        }
        return successMsg.toString();
    }

    private CampusStudents selectStudentByStuNo(String stuNo) {
        CampusStudents students;
        QueryWrapper<CampusStudents> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("stu_no", stuNo)
                .eq("status", '0')
                .eq("del_flag", '0')
                .last("LIMIT 1");
        List<CampusStudents> campusStudents = campusStudentsMapper.selectList(queryWrapper);
        students = (campusStudents == null || campusStudents.isEmpty()) ? null : campusStudents.get(0);
        return students;
    }

    private List<TreeSelect>  findClazz() {
        return sysDeptService.selectSchoolTreeList(new SysDept());
    }

    /**
     * 获取结构节点 填写到哪一级就返回哪一级
     * @param treeList
     * @param stu
     * @return
     */
    public void setDeptId(List<TreeSelect> treeList, CampusStudents stu) {
        String schoolName = stu.getSchoolName();
        String collegeName = stu.getCollege();
        String majorName = stu.getMajor();
        String className = stu.getClazz();
        Optional<TreeSelect> schoolOptional = treeList.stream()
                .filter(node -> node.getLabel().equals(schoolName))
                .findFirst();
        TreeSelect schoolNode = schoolOptional.orElse(null);
        if (schoolNode == null) {
            return;
        }
        stu.setSchoolId(String.valueOf(schoolNode.getId()));

        Optional<TreeSelect> collegeOptional = schoolNode.getChildren().stream()
                .filter(node -> node.getLabel().equals(collegeName))
                .findFirst();
        TreeSelect collegeNode = collegeOptional.orElse(null);
        if (collegeNode == null) {
            return;
        }
        stu.setCollegeId(String.valueOf(collegeNode.getId()));

        Optional<TreeSelect> majorOptional = collegeNode.getChildren().stream()
                .filter(node -> node.getLabel().equals(majorName))
                .findFirst();
        TreeSelect majorNode = majorOptional.orElse(null);
        if (majorNode == null) {
            return;
        }
        stu.setMajorId(String.valueOf(majorNode.getId()));

        Optional<TreeSelect> classOptional = majorNode.getChildren().stream()
                .filter(node -> node.getLabel().equals(className))
                .findFirst();
        TreeSelect clazzNod = classOptional.orElse(null);
        if (clazzNod == null) {
            return;
        }
        String clazzId = String.valueOf(clazzNod.getId());
        stu.setClazzId(clazzId);
        stu.setDeptId(clazzId);
    }


    @Override
    @Transactional
    public AjaxResult bindStudent(BindBody bindBody) {
        //获取用户
        Long userId = SecurityUtils.getLoginUser().getUserId();
        SysUser sysUser = userService.selectUserById(userId);
        sysUser.setNickName(bindBody.getStudentName());

        //判断学生
        CampusStudents student = isStudentExist(bindBody.getStuNo(), bindBody.getStudentName());
        if (student == null) {
           return AjaxResult.error("学号与姓名不匹配");
        }
        CampusUserStudent userBind = isUserBind(userId);
        //更新学生的姓名为昵称 部门
        sysUser.setDeptId(Long.valueOf(student.getDeptId()));
        userService.updateUserProfile(sysUser);
        CampusUserStudent userStudent = new CampusUserStudent();
        userStudent.setUserId(userId);
        userStudent.setStudentId(student.getStudentId());
        if (userBind != null) {
            //已经绑定将修改绑定
            UpdateWrapper<CampusUserStudent> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("user_id", userId).eq("stu_id", userBind.getStudentId());
            userStudentMapper.update(userStudent, updateWrapper);
            //更新user表字段
            userService.updateUser(sysUser);
            return AjaxResult.success("已更改绑定！");
        }
        //更新user表字段
        userService.updateUser(sysUser);
        userStudentMapper.insert(userStudent);
        return  AjaxResult.success("绑定成功！");
    }

    public CampusUserStudent isUserBind(Long userId) {
        QueryWrapper<CampusUserStudent> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        return userStudentMapper.selectOne(queryWrapper);
    }

    public CampusUserStudent getBindStudent(Long userId) {
        return userStudentMapper.selectOneToOneDetails(userId);
    }

    @Override
    public boolean checkStudentNoUnique(CampusStudents student) {
        if (student == null || StringUtils.isEmpty(student.getStuNo())) {
            return UserConstants.UNIQUE;
        }
        QueryWrapper<CampusStudents> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("stu_no", student.getStuNo())
                .eq("status", '0')
                .eq("del_flag", '0')
                .last("LIMIT 1");
        List<CampusStudents> campusStudents = campusStudentsMapper.selectList(queryWrapper);
        if (!campusStudents.isEmpty()) {
            // 存在与提交记录相同的数据 并且不是当前操作的数据 认定为重复
            CampusStudents info = campusStudents.get(0);
            if (!Objects.equals(info.getStudentId(), student.getStudentId())) {
                return UserConstants.NOT_UNIQUE;
            }

        }
        return UserConstants.UNIQUE;
    }

    @Override
    public List<CampusStudents> selectStudentListByNameAndDept(CampusStudents queryStudent) {
        return campusStudentsMapper.selectStudentListByNameAndDept(queryStudent);
    }

    public CampusStudents isStudentExist(String stuNo, String name) {
        QueryWrapper<CampusStudents> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("stu_no", stuNo)
                .eq("student_name", name)
                .eq("status","0")//正常状态
                .eq("del_flag","0");//未删除
        return campusStudentsMapper.selectOne(queryWrapper);
    }
}
